﻿using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using RevitProject.SpaceManager.Configuration;

using RevitProject.SpaceManager.ViewModel; // 可能需要引用 VM 来更新状态或获取数据
using RevitProject.Helper;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading.Tasks; // 如果有异步操作
using System.Windows;
using Autodesk.Revit.DB.Analysis; // Application.Current
using System.Linq;
using Autodesk.Revit.DB.Mechanical;
using System.IO;
using Newtonsoft.Json;
using System.Globalization;
using RevitProject.SpaceManager.ViewModel.SpaceViewModel;
using RevitProject.SpaceManager.ViewModel.DialogViewModelPart;
namespace RevitProject.SpaceManager.Core
{
    
    public static class SpaceTypeService
    {

        private static readonly string ConfigFilePath = GetConfigFilePath();
        private static string GetConfigFilePath()
        {
            try
            {
                string appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
                string configDir = Path.Combine(appDataPath, "维树科技", "空间管理器"); // 确保与 SpaceManagerVm 一致
                Directory.CreateDirectory(configDir);
                return Path.Combine(configDir, "SpaceTypeCategory.json");
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"获取配置文件路径时出错: {ex.Message}");
                return "SpaceTypeCategory.json"; // 降级路径
            }
        }

        private static List<CategoryNodeConfig> LoadConfiguration()
        {
            Debug.WriteLine($"SpaceTypeService: Loading config from: {ConfigFilePath}");
            try
            {
                if (File.Exists(ConfigFilePath))
                {
                    string json = File.ReadAllText(ConfigFilePath);
                    var config = JsonConvert.DeserializeObject<List<CategoryNodeConfig>>(json);
                    return config ?? new List<CategoryNodeConfig>();
                }
                Debug.WriteLine($"SpaceTypeService: Config file not found at {ConfigFilePath}. Returning empty list.");
            }
            catch (Exception ex) { Debug.WriteLine($"LoadConfiguration ERROR: {ex}"); }
            return new List<CategoryNodeConfig>();
        }

        //    新增：保存 JSON 配置的方法   
        private static bool SaveConfiguration(List<CategoryNodeConfig> configToSave)
        {
            Debug.WriteLine($"SpaceTypeService: Saving config list to: {ConfigFilePath}");
            if (configToSave == null)
            {
                Debug.WriteLine("SaveConfiguration WARNING: Input list is null. Saving empty array.");
                configToSave = new List<CategoryNodeConfig>();
            }
            try
            {
                string json = JsonConvert.SerializeObject(configToSave, Formatting.Indented, new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Ignore });
                File.WriteAllText(ConfigFilePath, json);
                Debug.WriteLine("Configuration saved successfully by Service.");
                return true;
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"SaveConfiguration ERROR: {ex}");
                TaskDialog.Show("保存错误", $"服务无法保存分类配置文件: {ex.Message}");
                return false;
            }
        }

        // --- DTOs (可以单独定义文件) ---
        public class SpaceTypeOperationData
        {
            public string Name { get; set; }
            public string TargetParentNodePath { get; set; } // 使用路径字符串代替 VM 引用传递
                                                             
            public double AreaPerPersonInternal { get; set; }
         
        }

        public class SpaceTypeUpdateData : SpaceTypeOperationData // 编辑时可能需要 ID
        {
            public ElementId ExistingTypeId { get; set; }
            public string OriginalName { get; set; } // 可能需要旧名称来更新 JSON
        }




        // --- 核心方法 ---

        /// <summary>
        /// 创建新的 HVACLoadSpaceType，更新 JSON 配置，并通知 ViewModel 刷新。
        /// </summary>
        public static async Task<ElementId> CreateSpaceTypeAsync(UIApplication uiApp, SpaceManagerVm mainVm, SpaceTypeUserInputData data)
        {
            Document doc = uiApp.ActiveUIDocument.Document;
            ElementId newTypeId = ElementId.InvalidElementId;
            bool revitSuccess = false;
            string failureReason = string.Empty;

            // 1. 执行 Revit 操作
            RevitContextHelper.Execute(app => {
                HVACLoadSpaceType newType = null;
                using (Transaction tx = new Transaction(doc, $"服务创建空间类型 {data.Name}"))
                {
                    try
                    {
                        tx.Start();

                        // a. 检查名称唯一性
                        bool isNameUnique = !new FilteredElementCollector(doc)
                                                .OfClass(typeof(HVACLoadSpaceType))
                                                .WhereElementIsElementType()
                                                .Any(el => el.Name.Equals(data.Name, StringComparison.OrdinalIgnoreCase));
                        if (!isNameUnique)
                        {
                            failureReason = $"名称 '{data.Name}' 已存在。";
                            tx.RollBack(); return;
                        }

                        // b. 创建 HVACLoadSpaceType
                        newType = HVACLoadSpaceType.Create(doc, data.Name);
                        if (newType == null)
                        {
                            failureReason = "HVACLoadSpaceType.Create 返回 null。";
                            tx.RollBack(); return;
                        }
                        newTypeId = newType.Id;

                        // c. 解析、转换并设置属性和参数
                        SetTypePropertiesFromData(newType, data); // 调用辅助方法设置

                        tx.Commit();
                        revitSuccess = true;
                        Debug.WriteLine($"Successfully created HVACLoadSpaceType '{data.Name}' (ID: {newTypeId}) in Revit.");

                    }
                    catch (Exception ex)
                    {
                        failureReason = $"创建或设置属性时出错: {ex.Message}";
                        Debug.WriteLine($"!!!!!! EXCEPTION during CreateSpaceType Transaction: {ex.ToString()}");
                        if (tx.HasStarted() && tx.GetStatus() == TransactionStatus.Started) tx.RollBack();
                        revitSuccess = false;
                    }
                } // using Transaction
            });// RevitContextHelper.Execute

            
            await Task.Delay(150);

          

            // 2. 更新 JSON 配置
            //    (获取父节点路径 - 需要从 DTO 的 SelectedParentNode 获取)
            string parentPath = GetNodePath(data.SelectedParentNode); // 需要此辅助方法
            bool jsonSuccess = UpdateJsonConfigForCreate(data.Name, parentPath); // 调用内部方法

            // 3. 通知 ViewModel 刷新
            bool vmUpdateSuccess = await NotifyViewModelsForUpdate(mainVm);

            // 4. 显示最终状态消息 (可选)
            if (!jsonSuccess) MessageBox.Show($"空间类型 '{data.Name}' 已在 Revit 中创建，但更新分类配置文件失败。", "警告", MessageBoxButton.OK, MessageBoxImage.Warning);
            // if (!vmUpdateSuccess) ... // NotifyViewModelsForUpdate 内部会刷新，通常不需要单独提示

            return newTypeId;
        }


        /// <summary>
        /// 编辑现有的 HVACLoadSpaceType，更新 JSON 配置（如果名称或位置改变），通知刷新。
        /// </summary>
        public static async Task<bool> UpdateSpaceTypeAsync(UIApplication uiApp, SpaceManagerVm mainVm, SpaceTypeUserInputData data) // 使用统一 DTO
        {
            // 验证输入 DTO 是否包含编辑所需信息
            if (data.ExistingTypeId == null || data.ExistingTypeId == ElementId.InvalidElementId)
            {
                Debug.WriteLine("UpdateSpaceTypeAsync ERROR: ExistingTypeId is missing in data.");
                MessageBox.Show("编辑操作失败：缺少要编辑的空间类型 ID。", "内部错误", MessageBoxButton.OK, MessageBoxImage.Error);
                return false;
            }

            long existingIdLong = data.ExistingTypeId.Value; 
            ElementId existingId = new ElementId(existingIdLong);

            Document doc = uiApp.ActiveUIDocument.Document;
            bool revitSuccess = false;
            bool nameChanged = !string.Equals(data.OriginalName, data.Name, StringComparison.OrdinalIgnoreCase);
            string failureReason = string.Empty;

            // 1. 执行 Revit 操作
            RevitContextHelper.Execute(app => {
                using (Transaction tx = new Transaction(doc, $"服务编辑空间类型 {data.OriginalName}"))
                {
                    try
                    {
                        tx.Start();

                        // a. 获取要编辑的元素
                        Element elementToEdit = doc.GetElement(existingId);
                        if (elementToEdit == null || !elementToEdit.IsValidObject)
                        {
                            failureReason = "找不到要编辑的空间类型元素。"; tx.RollBack(); return;
                        }
                        if (!(elementToEdit is HVACLoadSpaceType hvacTypeToEdit))
                        {
                            failureReason = "找到的元素不是有效的空间类型。"; tx.RollBack(); return;
                        }

                        // b. 如果名称改变，检查唯一性并重命名
                        if (nameChanged)
                        {
                            bool isNameUnique = !new FilteredElementCollector(doc)
                                                    .OfClass(typeof(HVACLoadSpaceType))
                                                    .WhereElementIsElementType()
                                                    .Any(el => el.Id != existingId && // 排除自身
                                                               el.Name.Equals(data.Name, StringComparison.OrdinalIgnoreCase));
                            if (!isNameUnique)
                            {
                                failureReason = $"新名称 '{data.Name}' 已被另一个空间类型使用。"; tx.RollBack(); return;
                            }
                            elementToEdit.Name = data.Name; // 重命名
                            Debug.WriteLine($"Renamed Space Type from '{data.OriginalName}' to '{data.Name}'.");
                        }

                        // c. 解析、转换并设置属性和参数
                        SetTypePropertiesFromData(hvacTypeToEdit, data); // 调用辅助方法设置

                        tx.Commit();
                        revitSuccess = true;
                        Debug.WriteLine($"Successfully updated HVACLoadSpaceType '{data.Name}' (ID: {data.ExistingTypeId.Value}) in Revit.");

                    }
                    catch (Exception ex)
                    {
                        failureReason = $"编辑或设置属性时出错: {ex.Message}";
                        Debug.WriteLine($"!!!!!! EXCEPTION during UpdateSpaceType Transaction: {ex.ToString()}");
                        if (tx.HasStarted() && tx.GetStatus() == TransactionStatus.Started) tx.RollBack();
                        revitSuccess = false;
                    }
                } 
            }); // RevitContextHelper.Execute

            // await Task.Delay(150); 

            //if (!revitSuccess)
            //{
            //    MessageBox.Show($"在 Revit 中编辑空间类型 '{data.OriginalName}' 失败。\n原因: {failureReason}", "编辑失败", MessageBoxButton.OK, MessageBoxImage.Error);
            //    return false;
            //}

            // 2. 更新 JSON 配置 (需要更复杂的编辑逻辑)
            //    获取新旧父节点路径
            string originalParentPath = GetNodePath(data.OriginalParentNode);
            string newParentPath = GetNodePath(data.SelectedParentNode);
            string originalParentJsonPath = GetNodePathForJson(data.OriginalParentNode); // 假设 data 是 SpaceTypeUserInputData
            string newParentJsonPath = GetNodePathForJson(data.SelectedParentNode);

            //     构造 SpaceTypeUpdateData 用于 JSON 编辑    
            var updateJsonData = new SpaceTypeUpdateData
            {
                ExistingTypeId = existingId, 
                OriginalName = data.OriginalName,
                Name = data.Name,
                TargetParentNodePath = newParentPath
            };

            bool jsonSuccess = UpdateJsonConfigForEditByInfo(
                        data.OriginalName,         // 原始名称
                        data.Name,                 // 新名称
                        originalParentJsonPath,    // 原始父路径
                        newParentJsonPath);         // 新父路径

            // 3. 通知 ViewModel 刷新
            bool vmUpdateSuccess = await NotifyViewModelsForUpdate(mainVm);

            if (!jsonSuccess) MessageBox.Show($"空间类型 '{data.Name}' 已在 Revit 中编辑，但更新分类配置文件失败。", "警告", MessageBoxButton.OK, MessageBoxImage.Warning);
            // if (!vmUpdateSuccess) ...

            return revitSuccess && jsonSuccess && vmUpdateSuccess; // 整体成功状态
        }


       
        /// <summary>
        /// 批量删除指定的 HVACLoadSpaceType，更新 JSON 配置，并通知 ViewModel 刷新。
        /// </summary>
        /// <param name="uiApp">Revit UI 应用程序。</param>
        /// <param name="mainVm">主 ViewModel 引用。</param>
        /// <param name="typeIdsToDelete">要删除的空间类型的 ElementId 列表。</param>
        /// <param name="nodePathsToDelete">对应要删除节点的路径列表 (顺序应与 typeIdsToDelete 一致，路径可能为 null)。</param>
        /// <returns>包含详细删除结果的 DeleteResult 对象。</returns>
        public static async Task<DeleteResult> DeleteSpaceTypesAsync(UIApplication uiApp, SpaceManagerVm mainVm, List<ElementId> typeIdsToDelete, List<string> nodePathsToDelete)
        {
            Document doc = uiApp.ActiveUIDocument.Document;
            var result = new DeleteResult();

            if (typeIdsToDelete == null || !typeIdsToDelete.Any())
            {
                result.ErrorMessage = "没有提供要删除的空间类型 ID。";
                return result;
            }
            if (nodePathsToDelete == null || nodePathsToDelete.Count != typeIdsToDelete.Count)
            {
                Debug.WriteLine("DeleteSpaceTypesAsync WARNING: Path list count mismatch or null. JSON update might be incomplete.");
                // 创建一个匹配大小的空路径列表，以避免索引错误，但标记 JSON 可能失败
                nodePathsToDelete = Enumerable.Repeat<string>(null, typeIdsToDelete.Count).ToList();
                result.JsonSuccess = false; // 预先标记 JSON 可能失败
            }


            List<string> successfullyDeletedPaths = new List<string>(); // 存储成功删除的对应路径

            // 1. 执行 Revit 删除 (事务处理)
            RevitContextHelper.Execute(app =>
            {
                using (Transaction tx = new Transaction(doc, $"服务批量删除空间类型"))
                {
                    try
                    {
                        tx.Start();
                        for (int i = 0; i < typeIdsToDelete.Count; i++)
                        {
                            ElementId id = typeIdsToDelete[i];
                            string path = nodePathsToDelete[i]; // 获取对应路径
                            Element elementToDelete = doc.GetElement(id);
                            string name = elementToDelete?.Name ?? $"ID {id}";

                            if (elementToDelete == null || !(elementToDelete is HVACLoadSpaceType))
                            {
                                result.Log.AppendLine($"跳过: 未找到有效的空间类型 ID {id}。");
                                result.SkippedCount++;
                                continue;
                            }

                            // 再次检查是否在使用中 (作为保险)
                            if (IsSpaceTypeInUse(doc, id))
                            {
                                result.Log.AppendLine($"跳过: 类型 '{name}' 正在使用中。");
                                result.SkippedCount++;
                                continue;
                            }

                            try
                            {
                                doc.Delete(id);
                                result.Log.AppendLine($"Revit 删除成功: '{name}' (ID: {id})。");
                                result.DeletedCount++;
                                result.SuccessfullyDeletedIds.Add(id); // <--- 填充结果对象的列表
                                if (path != null) // 只记录有效的路径
                                {
                                    successfullyDeletedPaths.Add(path);
                                }
                            }
                            catch (Exception deleteEx)
                            {
                                result.Log.AppendLine($"Revit 删除错误: '{name}' (ID: {id}): {deleteEx.Message}");
                                result.ErrorCount++;
                            }
                        }

                        if (result.DeletedCount > 0) // 只要有成功的就提交
                        {
                            tx.Commit();
                            result.RevitSuccess = true;
                        }
                        else // 没有成功的，回滚
                        {
                            result.Log.AppendLine("没有成功删除任何 Revit 对象，事务已回滚。");
                            tx.RollBack();
                            result.RevitSuccess = false; // 明确标记 Revit 操作失败
                        }
                    }
                    catch (Exception ex)
                    {
                        result.Log.Insert(0, $"执行删除事务时发生严重错误，操作已回滚: {ex.Message}\n");
                        if (tx.HasStarted() && tx.GetStatus() == TransactionStatus.Started) tx.RollBack();
                        result.ErrorCount = typeIdsToDelete.Count - result.DeletedCount - result.SkippedCount; // 更新错误计数
                        result.RevitSuccess = false;
                    }
                } // using Transaction
            }); // RevitContextHelper.Execute

            // 等待 Revit 操作完成
            // await Task.Delay(150); // 根据需要调整或移除

            // 2. 如果 Revit 删除有成功的，则尝试更新 JSON 配置
            if (result.RevitSuccess && successfullyDeletedPaths.Any()) // 只有 Revit 成功且有路径可删时才尝试
            {
                // 调用一个支持批量删除路径的 JSON 更新方法
                result.JsonSuccess = UpdateJsonConfigForDeleteMultiple(successfullyDeletedPaths);
                if (!result.JsonSuccess)
                {
                    result.ErrorMessage = (result.ErrorMessage ?? "") + "未能完全更新分类配置文件。";
                }
            }
            else if (result.RevitSuccess)
            {
                // Revit 成功，但没有路径信息（可能都是外部创建的类型），JSON 层面视为成功
                result.JsonSuccess = true;
            }
            else
            {
                // Revit 失败，JSON 肯定也失败
                result.JsonSuccess = false;
            }

            // 3. 如果 Revit 操作成功（至少删除了一个），则通知 ViewModel 刷新
            if (result.RevitSuccess)
            {
                result.VmUpdateSuccess = await NotifyViewModelsForUpdate(mainVm);
                if (!result.VmUpdateSuccess)
                {
                    result.ErrorMessage = (result.ErrorMessage ?? "") + "未能成功通知界面刷新。";
                }
            }
            else
            {
                result.VmUpdateSuccess = false; // Revit 失败，不刷新
            }

            // 设置最终的整体成功状态
            // result.OverallSuccess 在 DeleteResult 内部通过属性计算得出

            return result;
        }

        /// <summary>
        /// 尝试更新 JSON 配置以删除多个指定路径的节点。
        /// </summary>
        /// <param name="nodePathsToDelete">要删除的节点的相对路径列表 (例如 "分类A/子分类B")。</param>
        /// <returns>如果所有有效的删除尝试都成功（或没有有效路径需要删除）并且最终保存成功，则返回 true。</returns>
        private static bool UpdateJsonConfigForDeleteMultiple(List<string> nodePathsToDelete)
        {
            // 1. 处理无效输入或空列表
            if (nodePathsToDelete == null) return true; // null 列表视为无需操作，成功
                                                        // 去重并移除 null/空路径
            var distinctValidPaths = nodePathsToDelete.Where(p => !string.IsNullOrEmpty(p)).Distinct().ToList();
            if (!distinctValidPaths.Any()) return true; // 没有有效路径要删，视为成功

            bool overallSuccess = true;
            var configRootList = LoadConfiguration();
            if (configRootList == null || configRootList.Count == 0) return false;
            var rootConfig = configRootList[0];
            rootConfig.Children ??= new List<CategoryNodeConfig>();

            Debug.WriteLine($"UpdateJsonConfigForDeleteMultiple 调试: 准备删除以下路径: {string.Join("; ", distinctValidPaths)}");

            // 循环尝试删除每个不同的有效路径
            foreach (string path in distinctValidPaths)
            {
                Debug.WriteLine($"UpdateJsonConfigForDeleteMultiple 调试: 调用 RemoveNodeByPathRecursive 删除路径 '{path}'...");
                // ***** 关键调用点 *****
                if (!RemoveNodeByPathRecursive(rootConfig, path)) // 从根节点开始查找并移除
                {
                    overallSuccess = false;
                    Debug.WriteLine($"UpdateJsonConfigForDeleteMultiple 警告: 未能移除路径 '{path}' 对应的节点。");
                }
            }

            // 保存修改后的配置
            Debug.WriteLine($"UpdateJsonConfigForDeleteMultiple 调试: 准备保存配置...");
            if (!SaveConfiguration(configRootList))
            {
                overallSuccess = false;
                Debug.WriteLine("UpdateJsonConfigForDeleteMultiple 错误: 保存更新后的配置失败。");
            }
            else
            {
                Debug.WriteLine("UpdateJsonConfigForDeleteMultiple 调试: 配置保存成功。");
            }

            return overallSuccess;
        }

        /// <summary>
        /// 递归地根据相对路径从指定的父节点下移除子节点。
        /// </summary>
        /// <param name="parentNode">开始查找的父节点 (通常是根配置节点 "全部房间")。</param>
        /// <param name="pathToDelete">要删除节点的相对路径 (相对于 parentNode 的 Children)，例如 "分类A/子分类B"。</param>
        /// <returns>如果成功找到并移除了节点，则返回 true。</returns>
        private static bool RemoveNodeByPathRecursive(CategoryNodeConfig parentNode, string pathToDelete)
        {
            // 1. 基本检查
            if (parentNode == null || string.IsNullOrEmpty(pathToDelete))
            {
                Debug.WriteLine($"RemoveNodeByPathRecursive 调试: 输入无效 (parentNode is null? {parentNode == null}, path is null or empty? {string.IsNullOrEmpty(pathToDelete)})");
                return false;
            }
            parentNode.Children ??= new List<CategoryNodeConfig>();

            // 2. 解析路径段
            string[] segments = pathToDelete.Split('/');
            if (segments.Length == 0)
            {
                Debug.WriteLine($"RemoveNodeByPathRecursive 调试: 路径 '{pathToDelete}' 解析后为空。");
                return false;
            }

            // 3. 查找过程
            CategoryNodeConfig currentParent = parentNode;
            List<CategoryNodeConfig> currentChildren = parentNode.Children;
            Debug.WriteLine($"RemoveNodeByPathRecursive 调试: 开始查找路径 '{pathToDelete}'，起始父节点 '{currentParent.Name}'，子节点数 {currentChildren.Count}");

            // 遍历路径段，找到目标节点的直接父节点
            for (int i = 0; i < segments.Length - 1; i++) // 循环到倒数第二个段
            {
                string segment = segments[i];
                Debug.WriteLine($"RemoveNodeByPathRecursive 调试: 正在查找段 '{segment}' 于父节点 '{currentParent.Name}' 下...");
                if (currentChildren == null)
                {
                    Debug.WriteLine($"RemoveNodeByPathRecursive 错误: 父节点 '{currentParent.Name}' 的 Children 为 null，路径中断。");
                    return false;
                }

                var nextParent = currentChildren.FirstOrDefault(c => c.Name.Equals(segment, StringComparison.OrdinalIgnoreCase));
                if (nextParent == null)
                {
                    Debug.WriteLine($"RemoveNodeByPathRecursive 错误: 在父节点 '{currentParent.Name}' 下未找到名为 '{segment}' 的子节点。");
                    return false;
                }

                // 更新当前父节点和子节点列表
                currentParent = nextParent;
                currentChildren = currentParent.Children;
                currentParent.Children ??= new List<CategoryNodeConfig>(); // 确保下一级的 Children 列表存在
                Debug.WriteLine($"RemoveNodeByPathRecursive 调试: 已进入下一级父节点 '{currentParent.Name}'，子节点数 {currentChildren.Count}");
            }

            // 4. 定位并移除目标节点
            string nodeNameToRemove = segments.Last(); // 获取目标节点的名称
            Debug.WriteLine($"RemoveNodeByPathRecursive 调试: 准备在父节点 '{currentParent.Name}' 下移除节点 '{nodeNameToRemove}'...");

            CategoryNodeConfig nodeToRemove = null;
            int foundIndex = -1;
            if (currentChildren != null)
            {
                // 查找节点及其索引，使用 OrdinalIgnoreCase
                for (int idx = 0; idx < currentChildren.Count; idx++)
                {
                    if (currentChildren[idx].Name.Equals(nodeNameToRemove, StringComparison.OrdinalIgnoreCase))
                    {
                        nodeToRemove = currentChildren[idx];
                        foundIndex = idx;
                        break;
                    }
                }
            }


            if (nodeToRemove != null && currentChildren != null && foundIndex >= 0)
            {
                // 尝试从父节点的 Children 列表中移除
                // List<T>.Remove(T item) 可能依赖 Equals/GetHashCode，直接用 RemoveAt 更可靠
                try
                {
                    currentChildren.RemoveAt(foundIndex); // 使用索引移除
                    Debug.WriteLine($"已从父节点 '{currentParent.Name}' 的配置中移除节点 '{nodeNameToRemove}'。");
                    return true; // 移除成功
                }
                catch (ArgumentOutOfRangeException ex)
                {
                    // 理论上不应发生，因为我们刚找到了索引
                    Debug.WriteLine($"RemoveNodeByPathRecursive 错误: 移除节点时发生索引越界异常: {ex.Message}");
                    return false;
                }
                catch (Exception ex)
                {
                    Debug.WriteLine($"RemoveNodeByPathRecursive 错误: 移除节点时发生未知异常: {ex.Message}");
                    return false;
                }
            }
            else
            {
                Debug.WriteLine($"在父节点 '{currentParent.Name}' 下未找到要移除的节点 '{nodeNameToRemove}'。");
                return false; // 节点未找到
            }
        }


        /// <summary>
        /// 根据提供的无效节点路径列表，尝试从 JSON 配置文件中移除这些节点。
        /// 这个方法作为一种补充清理机制被调用。
        /// </summary>
        /// <param name="invalidNodePaths">要移除的节点的相对路径列表。</param>
        /// <returns>如果清理和保存操作成功（或无需清理），则返回 true。</returns>
        public static async Task<bool> RemoveInvalidNodesFromJsonAsync(List<string> invalidNodePaths) // <-- public static async
        {
            Debug.WriteLine($"SpaceTypeService: 收到清理 JSON 请求，包含 {invalidNodePaths?.Count ?? 0} 个无效路径。");
            if (invalidNodePaths == null || !invalidNodePaths.Any())
            {
                Debug.WriteLine("无需清理 JSON，路径列表为空。");
                return true;
            }

            bool success = false;
            try
            {
                // 在后台线程执行
                success = await Task.Run(() =>
                {
                    // --- 调用现有的（或待修复的）批量删除 JSON 方法 ---
                    return UpdateJsonConfigForDeleteMultiple(invalidNodePaths); // <-- 复用现有的删除逻辑
                });
            }
            catch (Exception ex) { Debug.WriteLine($"!!!!!! 清理 JSON 时发生异常: {ex.ToString()}"); success = false; }

            if (!success) { Debug.WriteLine("JSON 清理操作执行失败或部分失败。"); }
            return success;
        }
       

    

        // --- 私有辅助方法 ---

        private static bool IsSpaceTypeInUse(Document doc, ElementId typeId)
        {
            // 查找使用该类型的 Space
            return new FilteredElementCollector(doc)
                .OfCategory(BuiltInCategory.OST_MEPSpaces)
                .WhereElementIsNotElementType()
                .Any(s => (s as Space)?.SpaceTypeId == typeId);
        }


        /// <summary>
        /// 更新 JSON 配置以添加新节点。
        /// </summary>
        /// <param name="newNodeName">新节点的名称。</param>
        /// <param name="parentNodePath">目标父节点的路径 (例如 "功能房间/办公室")，如果为 null 或空，则添加到根节点 ("全部房间") 下。</param>
        /// <returns>如果更新并保存成功，则返回 true。</returns>
        private static bool UpdateJsonConfigForCreate(string newNodeName, string parentNodePath)
        {
            try
            {
                var configRootList = LoadConfiguration();
                if (configRootList == null) return false;
                CategoryNodeConfig rootConfig;
                if (configRootList.Count == 0)
                {
                    rootConfig = new CategoryNodeConfig { Name = "全部房间", Children = new List<CategoryNodeConfig>() };
                    configRootList.Add(rootConfig);
                }
                else
                {
                    rootConfig = configRootList[0]; // Assume first is root
                    rootConfig.Children ??= new List<CategoryNodeConfig>();
                }

                // 查找父配置节点
                CategoryNodeConfig parentConfigNode = string.IsNullOrEmpty(parentNodePath)
                    ? rootConfig // 如果路径为空，父节点是根
                    : FindConfigNodeByPath(rootConfig.Children, parentNodePath);

                if (parentConfigNode == null)
                {
                    Debug.WriteLine($"UpdateJsonConfigForCreate WARNING: Parent node not found for path '{parentNodePath ?? "Root"}'. Adding to root.");
                    parentConfigNode = rootConfig; // 找不到就添加到根
                }
                parentConfigNode.Children ??= new List<CategoryNodeConfig>();

                // 检查名称冲突
                if (parentConfigNode.Children.Any(c => c.Name.Equals(newNodeName, StringComparison.OrdinalIgnoreCase)))
                {
                    Debug.WriteLine($"UpdateJsonConfigForCreate INFO: Node '{newNodeName}' already exists under parent '{parentConfigNode.Name}'. Skipping add.");
                    return true; // 已存在视为成功
                }

                // 添加新节点
                var newNodeConfig = new CategoryNodeConfig { Name = newNodeName, Children = new List<CategoryNodeConfig>() };
                parentConfigNode.Children.Add(newNodeConfig);
                parentConfigNode.Children = parentConfigNode.Children.OrderBy(c => c.Name).ToList(); // 排序

                // 保存
                return SaveConfiguration(configRootList);
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"UpdateJsonConfigForCreate EXCEPTION: {ex}");
                return false;
            }
        }

        /// <summary>
        /// 更新 JSON 配置以反映编辑操作（重命名或移动），使用明确的名称和路径信息。
        /// </summary>
        /// <param name="originalName">节点的原始名称。</param>
        /// <param name="newName">节点的新名称。</param>
        /// <param name="originalParentPath">节点原始父节点的相对路径 (null 表示根)。</param>
        /// <param name="newParentPath">节点新父节点的相对路径 (null 表示根)。</param>
        /// <returns>如果更新并保存成功，则返回 true。</returns>
        private static bool UpdateJsonConfigForEditByInfo(string originalName, string newName, string originalParentPath, string newParentPath) // <-- 改名并修改参数
        {
            try
            {
                var configRootList = LoadConfiguration();
                if (configRootList == null || configRootList.Count == 0) {  return false; }
                var rootConfig = configRootList[0];
                rootConfig.Children ??= new List<CategoryNodeConfig>();

                // 1. 查找旧父配置节点
                CategoryNodeConfig oldParentConfigNode = string.IsNullOrEmpty(originalParentPath)
             ? rootConfig // 如果原始路径为空，假设父节点是根
             : FindConfigNodeByPath(rootConfig.Children, originalParentPath);
                CategoryNodeConfig nodeToEditConfig = null;
                if (oldParentConfigNode != null)
                { // 只有在找到旧父节点时才查找旧节点
                    oldParentConfigNode.Children ??= new List<CategoryNodeConfig>();
                    nodeToEditConfig = oldParentConfigNode.Children.FirstOrDefault(c => c.Name.Equals(originalName, StringComparison.OrdinalIgnoreCase));
                }
                else
                {
                    // 如果 originalParentPath 有值但找不到，记录警告但继续，视为 nodeToEditConfig 未找到
                    Debug.WriteLine($"UpdateJsonConfigForEdit WARNING: Original parent path '{originalParentPath}' not found in JSON. Assuming original node was not categorized.");
                }


                //查找新父配置节点
                CategoryNodeConfig newParentConfigNode = string.IsNullOrEmpty(newParentPath)
                    ? rootConfig
                    : FindConfigNodeByPath(rootConfig.Children, newParentPath);
                if (newParentConfigNode == null) { /*...*/ Debug.WriteLine($"ERROR: Cannot find new parent for path: {newParentPath}"); return false; } // 增加日志
                newParentConfigNode.Children ??= new List<CategoryNodeConfig>();

                // 检查是否需要移动或重命名
                bool nameChanged = !originalName.Equals(newName, StringComparison.OrdinalIgnoreCase);
                // 修正父节点比较逻辑：直接比较父节点对象引用可能不准确，应该比较路径
                bool parentPathChanged = !string.Equals(originalParentPath, newParentPath, StringComparison.OrdinalIgnoreCase);





                // --- 逻辑分支 ---

                // CASE 1: 原始节点在 JSON 中找到了 (nodeToEditConfig != null)
                if (nodeToEditConfig != null)
                {
                    Debug.WriteLine($"UpdateJsonConfigForEdit: Found existing node '{originalName}' in JSON under '{oldParentConfigNode?.Name ?? "Root"}'. Processing standard edit/move.");

                    // 检查目标位置的名称冲突 (仅当名称或父路径改变时需要检查)
                    if (nameChanged || parentPathChanged)
                    {
                        // 目标父节点是 newParentConfigNode
                        if (newParentConfigNode.Children.Any(c => c != nodeToEditConfig && c.Name.Equals(newName, StringComparison.OrdinalIgnoreCase)))
                        {
                            Debug.WriteLine($"ERROR: Name conflict for '{newName}' under target parent '{newParentConfigNode.Name}'.");
                            MessageBox.Show($"无法移动或重命名，因为目标父分类 '{newParentConfigNode.Name}' 下已存在名称 '{newName}'。", "操作失败", MessageBoxButton.OK, MessageBoxImage.Warning);
                            return false;
                        }
                    }

                    // 执行移动/重命名
                    if (parentPathChanged) // 父节点变了 (移动)
                    {
                        if (!oldParentConfigNode.Children.Remove(nodeToEditConfig)) { /*...*/ return false; }
                        if (nameChanged) nodeToEditConfig.Name = newName; // 更新名称
                        newParentConfigNode.Children.Add(nodeToEditConfig); // 添加到新父节点
                        newParentConfigNode.Children = newParentConfigNode.Children.OrderBy(c => c.Name).ToList();
                        Debug.WriteLine($"Moved '{nodeToEditConfig.Name}' from '{oldParentConfigNode.Name}' to '{newParentConfigNode.Name}'.");
                    }
                    else if (nameChanged) // 仅重命名，父节点未变
                    {
                        nodeToEditConfig.Name = newName;
                        oldParentConfigNode.Children = oldParentConfigNode.Children.OrderBy(c => c.Name).ToList();
                        Debug.WriteLine($"Renamed node to '{nodeToEditConfig.Name}' under parent '{oldParentConfigNode.Name}'.");
                    }
                    else // 名称和父路径都没变
                    {
                        Debug.WriteLine("UpdateJsonConfigForEdit: No change in name or parent path for existing JSON node.");
                        return true; // JSON 结构无需更新
                    }
                }
                // CASE 2: 原始节点在 JSON 中未找到 (nodeToEditConfig == null) - 用户正在为现有 Revit 类型指定分类或重命名并分类
                else
                {
                    Debug.WriteLine($"UpdateJsonConfigForEdit: Original node '{originalName}' not found in JSON. Checking if categorization is needed.");

                    // 只有当用户明确指定了一个父分类（newParentPath 不为空）或者重命名了（即使父分类是根），才需要添加到 JSON
                    if (!string.IsNullOrEmpty(newParentPath) || nameChanged) // 条件修改：如果指定了父分类，或即使父分类是根但改了名
                    {
                        Debug.WriteLine($"Attempting to ADD node '{newName}' to JSON under parent '{newParentConfigNode.Name}'.");

                        // 检查新父节点下是否存在同名节点
                        if (newParentConfigNode.Children.Any(c => c.Name.Equals(newName, StringComparison.OrdinalIgnoreCase)))
                        {
                            Debug.WriteLine($"ERROR: Cannot add node. Name conflict for '{newName}' under target parent '{newParentConfigNode.Name}'.");
                            MessageBox.Show($"无法将分类 '{newName}' 添加到父分类 '{newParentConfigNode.Name}'，因为该名称已存在。", "操作失败", MessageBoxButton.OK, MessageBoxImage.Warning);
                            return false;
                        }

                        // 添加新节点配置
                        var newNodeConfig = new CategoryNodeConfig { Name = newName, Children = new List<CategoryNodeConfig>() };
                        newParentConfigNode.Children.Add(newNodeConfig);
                        newParentConfigNode.Children = newParentConfigNode.Children.OrderBy(c => c.Name).ToList(); // 排序
                        Debug.WriteLine($"Added new node '{newName}' to JSON under '{newParentConfigNode.Name}'.");
                    }
                    else
                    {
                        // 如果原始节点不在 JSON 中，用户也没有选择父分类，也没有改名，则无需操作 JSON
                        Debug.WriteLine("UpdateJsonConfigForEdit: Original node not in JSON and no parent selected or name changed. No JSON update needed.");
                        return true; // JSON 层面认为是成功的
                    }
                }

                // --- 保存 ---
                return SaveConfiguration(configRootList);
            }
            catch (Exception ex) { /*...*/ MessageBox.Show($"更新 JSON 配置时出错: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error); return false; } // 添加错误提示
        }



        private static CategoryNodeConfig FindConfigNodeByPathRecursive(List<CategoryNodeConfig> nodes, string[] pathSegments, int currentSegmentIndex)
        {
            if (nodes == null || currentSegmentIndex >= pathSegments.Length) return null;

            string targetName = pathSegments[currentSegmentIndex];
            var foundNode = nodes.FirstOrDefault(n => n.Name.Equals(targetName, StringComparison.OrdinalIgnoreCase));

            if (foundNode == null) return null;

            if (currentSegmentIndex == pathSegments.Length - 1)
                return foundNode;
            else
                return FindConfigNodeByPathRecursive(foundNode.Children, pathSegments, currentSegmentIndex + 1);
        }

        // 1. GetParentPath(string nodeName, CategoryNodeConfig root)
        // 获取指定名称节点的父节点路径
        private static string GetParentPath(string nodeName, CategoryNodeConfig root)
        {
            if (string.IsNullOrEmpty(nodeName) || root == null)
            {
                // 如果节点名称为空或根节点为空，则无法查找
                return null;
            }
            var pathStack = new Stack<string>();
            // 路径从根节点开始
            pathStack.Push(root.Name);
            // 调用递归辅助方法，从根节点开始查找
            return FindParentPathRecursiveByName(root, nodeName, pathStack);
        }

        // 递归辅助方法：按名称查找目标节点的父节点路径
        private static string FindParentPathRecursiveByName(CategoryNodeConfig currentNode, string targetName, Stack<string> currentPath)
        {
            // 如果当前节点为空或没有子节点，则在此分支中找不到
            if (currentNode?.Children == null) return null;

            // 遍历当前节点的子节点
            foreach (var child in currentNode.Children)
            {
                // 检查当前子节点是否是目标节点
                if (child.Name.Equals(targetName, StringComparison.OrdinalIgnoreCase))
                {
                    // 找到了目标节点(child)，那么它的父节点就是 currentNode
                    // currentPath 当前存储的是到达 currentNode 的路径
                    return string.Join("/", currentPath); // 返回父节点的路径
                }

                // 如果当前子节点不是目标，则递归搜索其子孙节点
                currentPath.Push(child.Name); // 将当前子节点加入路径栈，准备深入搜索
                string foundPath = FindParentPathRecursiveByName(child, targetName, currentPath);
                if (foundPath != null)
                {
                    // 如果在子孙节点中找到了，直接返回找到的父路径
                    return foundPath;
                }
                currentPath.Pop(); // 回溯：如果在此子节点的子孙中没找到，将其从路径栈中移除
            }

            // 在当前节点的所有子孙中都未找到目标节点
            return null;
        }


        // 2. GetParentPath(CategoryNodeConfig node, CategoryNodeConfig root)
        // 获取指定节点实例的父节点路径
        private static string GetParentPath(CategoryNodeConfig nodeToFind, CategoryNodeConfig root)
        {
            if (nodeToFind == null || root == null || nodeToFind == root)
            {
                // 如果要查找的节点为空、根节点为空，或者要查找的就是根节点本身（根没有父路径），则返回 null
                return null;
            }
            var pathStack = new Stack<string>();
            // 路径从根节点开始
            pathStack.Push(root.Name);
            // 调用递归辅助方法，从根节点开始查找
            return FindParentPathRecursiveByRef(root, nodeToFind, pathStack);
        }

        // 递归辅助方法：按引用查找目标节点的父节点路径
        private static string FindParentPathRecursiveByRef(CategoryNodeConfig currentNode, CategoryNodeConfig targetNode, Stack<string> currentPath)
        {
            // 如果当前节点为空或没有子节点，则在此分支中找不到
            if (currentNode?.Children == null) return null;

            // 检查当前节点的子节点中是否包含目标节点（按引用比较）
            if (currentNode.Children.Contains(targetNode))
            {
                // 找到了目标节点(它是 currentNode 的子节点)，那么它的父节点就是 currentNode
                // currentPath 当前存储的是到达 currentNode 的路径
                return string.Join("/", currentPath); // 返回父节点的路径
            }

            // 如果目标不是直接子节点，则递归搜索每个子节点的子孙
            foreach (var child in currentNode.Children)
            {
                currentPath.Push(child.Name); // 将当前子节点加入路径栈，准备深入搜索
                string foundPath = FindParentPathRecursiveByRef(child, targetNode, currentPath);
                if (foundPath != null)
                {
                    // 如果在子孙节点中找到了，直接返回找到的父路径
                    return foundPath;
                }
                currentPath.Pop(); // 回溯：如果在此子节点的子孙中没找到，将其从路径栈中移除
            }

            // 在当前节点的所有子孙中都未找到目标节点
            return null;
        }

        private static void SetTypePropertiesFromData(HVACLoadSpaceType type, SpaceTypeUserInputData data)
        {
            // 注意：此方法在 Revit 事务内部调用
            Document doc = type.Document; // 获取文档对象

            // --- 解析和设置 HVAC 参数 ---
            double? val; // 用于接收解析结果

            // 人均面积 (m²/人 -> ft²/人)
            val = ParseDouble(data.AreaPerPerson);
            if (val.HasValue) type.AreaPerPerson = UnitUtils.ConvertToInternalUnits(val.Value, UnitTypeId.SquareMeters); // API 接收面积单位? 需要确认！通常是 ft²

            // 照明负荷密度 (W/m² -> W/ft²)
            val = ParseDouble(data.LightingLoadDensity);
            if (val.HasValue) type.LightingLoadDensity = UnitUtils.ConvertToInternalUnits(val.Value, UnitTypeId.WattsPerSquareMeter); // API 接收 W/m²? 需要确认！通常 W/ft²

            // 设备负荷密度 (W/m² -> W/ft²)
            val = ParseDouble(data.PowerLoadDensity);
            if (val.HasValue) type.PowerLoadDensity = UnitUtils.ConvertToInternalUnits(val.Value, UnitTypeId.WattsPerSquareMeter); // API 接收 W/m²? 需要确认！通常 W/ft²

            // 人员显热 (W/人 -> W/人)
            val = ParseDouble(data.SensibleHeatGainPerPerson);
            if (val.HasValue) type.SensibleHeatGainPerPerson = UnitUtils.ConvertToInternalUnits(val.Value, UnitTypeId.Watts); // API 单位是 Watts

            // 人员潜热 (W/人 -> W/人)
            val = ParseDouble(data.LatentHeatGainPerPerson);
            if (val.HasValue) type.LatentHeatGainPerPerson = UnitUtils.ConvertToInternalUnits(val.Value, UnitTypeId.Watts); // API 单位是 Watts

            // 供暖设定点 (°C -> K or R)
            val = ParseDouble(data.HeatingSetpoint);
            if (val.HasValue) type.HeatingSetPoint = UnitUtils.ConvertToInternalUnits(val.Value, UnitTypeId.Celsius); // API 单位是 K 或 R

            // 制冷设定点 (°C -> K or R)
            val = ParseDouble(data.CoolingSetpoint);
            if (val.HasValue) type.CoolingSetPoint = UnitUtils.ConvertToInternalUnits(val.Value, UnitTypeId.Celsius); // API 单位是 K 或 R

            // 加湿设定点 (% -> 0-1 ratio)
            val = ParsePercentage(data.HumidificationSetpoint);
            if (val.HasValue) type.HumidificationSetPoint = val.Value / 100.0; // API 单位是 0-1

            // 除湿设定点 (% -> 0-1 ratio)
            val = ParsePercentage(data.DehumidificationSetpoint);
            if (val.HasValue) type.DehumidificationSetPoint = val.Value / 100.0; // API 单位是 0-1

            // 渗透风量 (L/(s·m²) -> L/(s·m²)) - 通过参数设置
            val = ParseDouble(data.InfiltrationAirflowPerArea);
            if (val.HasValue)
            {
                Parameter infiltrationParam = type.get_Parameter(BuiltInParameter.SPACE_INFILTRATION_PARAM); // 确认这个 BIP 是否正确
                if (infiltrationParam != null && !infiltrationParam.IsReadOnly)
                {
                    try { infiltrationParam.Set(UnitUtils.ConvertToInternalUnits(val.Value, UnitTypeId.LitersPerSecondSquareMeter)); } // API 参数单位 L/(s·m²)? 确认！
                    catch (Exception ex) { Debug.WriteLine($"Error setting Infiltration Parameter: {ex.Message}"); }
                }
                else { Debug.WriteLine("Could not find or set Infiltration Parameter."); }
            }

            // 每人新风量 (m³/h -> L/s or CFM) - 需要确认 API 单位！ 假设 API 是 L/s
            val = ParseDouble(data.OutsideAirPerPerson);
            if (val.HasValue) type.OutdoorAirPerPerson = UnitUtils.ConvertToInternalUnits(val.Value, UnitTypeId.LitersPerSecond); //    极度需要确认 API 单位   

            // 每面积新风量 (L/(s·m²) -> L/(s·m²))
            val = ParseDouble(data.OutsideAirPerArea);
            if (val.HasValue) type.OutdoorAirPerArea = UnitUtils.ConvertToInternalUnits(val.Value, UnitTypeId.LitersPerSecondSquareMeter); // API 单位 L/(s·m²)? 确认！

            // 换气次数 (/h -> /h)
            val = ParseDouble(data.AirChangesPerHour);
            if (val.HasValue) type.AirChangesPerHour = val.Value; // API 单位 /h

            // --- 设置明细表 ---
            SetScheduleParameterByName(type, BuiltInParameter.SPACE_OCCUPANCY_SCHEDULE_PARAM, data.OccupancySchedule);
            SetScheduleParameterByName(type, BuiltInParameter.SPACE_LIGHTING_SCHEDULE_PARAM, data.LightingSchedule);
            SetScheduleParameterByName(type, BuiltInParameter.SPACE_POWER_SCHEDULE_PARAM, data.PowerSchedule);

            // --- 设置新风方法 ---
            OutdoorAirFlowStandard standard = ConvertDisplayAirMethodToEnum(data.OutsideAirMethod);
            if (standard != default(OutdoorAirFlowStandard)) // 避免设置无效值
            {
                try { type.OutdoorAirFlowStandard = standard; }
                catch (Exception ex) { Debug.WriteLine($"Error setting OutdoorAirFlowStandard: {ex.Message}"); }
            }
            else { Debug.WriteLine($"Could not convert display air method '{data.OutsideAirMethod}' to enum."); }
        }


        // ---     私有辅助方法 - 解析字符串     ---
        private static double? ParseDouble(string value)
        {
            if (string.IsNullOrWhiteSpace(value)) return null; // 允许空值
            if (double.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out double result))
            {
                return result;
            }
            Debug.WriteLine($"ParseDouble WARNING: Could not parse '{value}' to double.");
            return null; 
        }

        private static double? ParsePercentage(string value)
        {
            if (string.IsNullOrWhiteSpace(value)) return null;
            value = value.Replace("%", "").Trim(); // 移除百分号
            return ParseDouble(value); // 使用通用的 double 解析
        }

        // ---     私有辅助方法 - 查找明细表     ---
        private static ElementId FindScheduleIdByName(Document doc, string name)
        {
            if (string.IsNullOrWhiteSpace(name) || name.Equals("无", StringComparison.OrdinalIgnoreCase))
                return ElementId.InvalidElementId;

            // Revit 2023 及更新版本推荐使用 ElementNameFilter
            // var nameFilter = new ElementNameFilter(name, false); // false for case-insensitive in older versions? check API doc
            // FilteredElementCollector collector = new FilteredElementCollector(doc)
            //                                     .OfClass(typeof(ViewSchedule))
            //                                     .WherePasses(nameFilter);
            // return collector.FirstElementId() ?? ElementId.InvalidElementId;

            // 兼容旧版本的 LINQ 方法
            return new FilteredElementCollector(doc)
                   .OfClass(typeof(ViewSchedule))
                   .WhereElementIsNotElementType()
                   .FirstOrDefault(s => s.Name.Equals(name, StringComparison.OrdinalIgnoreCase))?.Id ?? ElementId.InvalidElementId;
        }

        // ---     私有辅助方法 - 设置明细表参数     ---
        private static void SetScheduleParameterByName(HVACLoadSpaceType type, BuiltInParameter bip, string scheduleName)
        {
            Document doc = type.Document;
            Parameter param = type.get_Parameter(bip);
            if (param == null || param.IsReadOnly)
            {
                Debug.WriteLine($"SetScheduleParameterByName WARNING: Parameter {bip} not found or is read-only for type '{type.Name}'.");
                return;
            }

            ElementId scheduleId = FindScheduleIdByName(doc, scheduleName); // 查找 ID (InvalidElementId if "无" or not found)

            try
            {
                param.Set(scheduleId); // 直接设置 ID，即使是 InvalidElementId 也会清除当前值
                                       // Debug.WriteLine($"Set schedule parameter {bip} to '{scheduleName ?? "None"}' (ID: {scheduleId}) for type '{type.Name}'.");
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"Error setting schedule parameter {bip} for type '{type.Name}' (Schedule: '{scheduleName}'): {ex.Message}");
            }
        }

        // ---     私有辅助方法 - 转换新风方法     ---
        private static OutdoorAirFlowStandard ConvertDisplayAirMethodToEnum(string displayName)
        {
            if (string.IsNullOrWhiteSpace(displayName)) return default; // 或者返回一个默认枚举值？

            switch (displayName)
            {
                case "按人数和面积": return OutdoorAirFlowStandard.ByPeopleAndByArea;
                case "按换气次数": return OutdoorAirFlowStandard.ByACH;
                case "最大值 (按人数, 按面积)": return OutdoorAirFlowStandard.MaxByPeople_ByArea; // 确认枚举值是否匹配
                case "最大值 (按换气次数, 按人数和面积)": return OutdoorAirFlowStandard.MaxByACH_ByPeopleByArea; // 确认枚举值是否匹配
                case "最大值 (按换气次数, 按面积, 按人数)": return OutdoorAirFlowStandard.MaxByACH_ByArea_ByPeople; // 确认枚举值是否匹配
                                                                                                      // 添加其他可能的映射
                default:
                    // 尝试直接按名称解析枚举 (忽略大小写)
                    if (Enum.TryParse<OutdoorAirFlowStandard>(displayName, true, out var standard))
                    {
                        return standard;
                    }
                    return default; // 返回默认值表示无法识别
            }
        }

        // ---     私有辅助方法 - 获取节点路径     ---
        private static string GetNodePath(SpaceTypeTreeNodeViewModel node)
        {
            if (node == null || node.IsAllSpacesNode) return null; // 根或无父节点返回 null
            var pathStack = new Stack<string>();
            var currentNode = node;
            while (currentNode != null && !currentNode.IsAllSpacesNode) // 向上直到遇到根或 null
            {
                pathStack.Push(currentNode.DisplayName);
                currentNode = currentNode.Parent;
            }
            // 不包含根节点 "全部空间" 的路径
            return string.Join("/", pathStack);
        }

        // 通知所有相关 ViewModel 刷新的方法
        private static async Task<bool> NotifyViewModelsForUpdate(SpaceManagerVm mainVm)
        {
            bool spaceVmSuccess = false;
            bool hvacVmSuccess = false;
            try
            {
                // 使用 Dispatcher 确保在 UI 线程上调用刷新命令
                await Application.Current.Dispatcher.InvokeAsync(async () =>
                {
                    // 刷新 SpaceTabViewModel (执行完全刷新)
                    if (mainVm.SpaceVM?.LoadSpaceDataCommand != null && mainVm.SpaceVM.LoadSpaceDataCommand.CanExecute(null))
                    {
                        await mainVm.SpaceVM.LoadSpaceDataCommand.ExecuteAsync(null);
                        spaceVmSuccess = true;
                    }
                    else { Debug.WriteLine("NotifyViewModels: SpaceVM refresh command cannot execute."); }

                    // 刷新 HAVCLoadViewModel
                    if (mainVm.HAVCLoadVM?.LoadDataCommand != null && mainVm.HAVCLoadVM.LoadDataCommand.CanExecute(null))
                    {
                        await mainVm.HAVCLoadVM.LoadDataCommand.ExecuteAsync(null);
                        hvacVmSuccess = true;
                    }
                    else { Debug.WriteLine("NotifyViewModels: HAVCLoadVM refresh command cannot execute."); }
                });
                return spaceVmSuccess && hvacVmSuccess; // 或者根据业务逻辑决定返回哪个
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"NotifyViewModelsForUpdate ERROR: {ex}");
                return false;
            }
        }

        // Inside SpaceTypeService.cs
        /// <summary>
        /// 获取 ViewModel 节点在用户定义树中的相对路径，用于 JSON 操作。
        /// 返回 null 如果节点是根占位符或无法确定路径。
        /// </summary>
        private static string GetNodePathForJson(SpaceTypeTreeNodeViewModel node)
        {
            // 返回 null 对于特殊根节点或无效输入
            if (node == null || node.IsAllSpacesNode || node.DisplayName == "(添加到根分类)" || node.DisplayName == "(根分类)")
                return null;

            var pathSegments = new Stack<string>();
            var currentNode = node;

            // 向上遍历，直到父节点是 "全部空间" 节点或 null
            // 将节点名称压入栈
            while (currentNode != null && (currentNode.Parent == null || !currentNode.Parent.IsAllSpacesNode))
            {
                pathSegments.Push(currentNode.DisplayName);
                currentNode = currentNode.Parent;
                // 安全检查，防止无限循环
                if (pathSegments.Count > 100)
                {
                    Debug.WriteLine($"GetNodePathForJson ERROR: Path too deep or possible loop detected for node '{node.DisplayName}'");
                    return null; // 返回 null 表示路径查找失败
                }
            }
            // 如果循环结束后 currentNode 仍然有效，说明它是根用户节点，压入它的名字
            if (currentNode != null && currentNode.Parent != null && currentNode.Parent.IsAllSpacesNode)
            {
                pathSegments.Push(currentNode.DisplayName);
            }
            else if (currentNode != null && currentNode.Parent == null)
            {
                // 根用户节点（理论上不应该发生，如果树总是挂在 "All Spaces" 下）
                pathSegments.Push(currentNode.DisplayName);
                Debug.WriteLine($"GetNodePathForJson WARNING: Node '{node.DisplayName}' seems to be a root user node.");
            }


            // 如果栈为空（例如，传入的节点就是 "All Spaces" 的直接子节点但处理逻辑有误），返回 null
            if (pathSegments.Count == 0) return null;

            // 反转栈内容并用 "/" 连接成路径
            return string.Join("/", pathSegments); // Stack<T> 本身是后进先出，直接 Join 就是正确的顺序
        }

        // Inside SpaceTypeService.cs
        /// <summary>
        /// 根据相对路径在 CategoryNodeConfig 树中查找节点。
        /// </summary>
        /// <param name="startingChildren">开始查找的子节点列表（通常是 "全部空间" 的 Children）。</param>
        /// <param name="path">相对路径，例如 "功能房间/办公室"。</param>
        /// <returns>找到的 CategoryNodeConfig，如果未找到则返回 null。</returns>
        private static CategoryNodeConfig FindConfigNodeByPath(List<CategoryNodeConfig> startingChildren, string path)
        {
            // 如果路径为空，表示目标是根下的直接子节点，或者操作是在根上进行（例如添加到根），
            // 这种情况下查找无意义，调用者应该直接使用 startingChildren。
            // 但为了查找父节点，如果 path 为 null，表示父节点是 "全部空间" 本身。
            if (string.IsNullOrEmpty(path)) return null; // 返回 null 表示路径指向根下的直接子节点

            string[] segments = path.Split('/');
            List<CategoryNodeConfig> currentLevelChildren = startingChildren;
            CategoryNodeConfig foundNode = null;

            foreach (string segment in segments)
            {
                if (currentLevelChildren == null) return null; // 无法深入
                foundNode = currentLevelChildren.FirstOrDefault(c => c.Name.Equals(segment, StringComparison.OrdinalIgnoreCase));
                if (foundNode == null) return null; // 未找到当前段
                currentLevelChildren = foundNode.Children; // 移动到下一层
            }
            return foundNode; // 返回最后找到的节点
        }




    }

}